package ac.snu.street;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Set;

import android.os.Handler;
import android.os.Message;
import android.util.Log;

public class RemoteDatabase {
	public static final String SERVERIP = "147.46.78.228";
	public static final int PORT = 4444;
	
	private Handler updateHandler;
	private Message handlerMessage;
	private String msgSend;
	
	public RemoteDatabase(Handler handler) {
		updateHandler = handler;	
		msgSend = null;
	}

	public void send(String msg) {
		msgSend = msg;
		
		Thread cThread = new Thread(new TCPClient());
		cThread.start();
	}

	public void post(StreetNote note) {
		msgSend = "POST" + "\t" + note.latitude + "\t" + note.longitude + "\t" + note.title + "\t" + note.contents;
		handlerMessage = new Message();
		handlerMessage.what = StreetPostActivity.MSG_ACK_INSERT;
		
		Thread cThread = new Thread(new TCPClient());
		cThread.start();
	}
	
	public void update(int id, String contents) {
		msgSend = "UPDT" + "\t" + id + "\t" + contents;
		handlerMessage = new Message();
		handlerMessage.what = StreetPostActivity.MSG_ACK_MODIFY;
		
		Thread cThread = new Thread(new TCPClient());
		cThread.start();
	}
	
	public void delete(int id) {
		msgSend = "DELT" + "\t" + id;
		handlerMessage = new Message();
		handlerMessage.what = StreetPostActivity.MSG_ACK_MODIFY;
		
		Thread cThread = new Thread(new TCPClient());
		cThread.start();
	}
	
	public void getNotesAround(int latitude, int longitude, int range) {
		msgSend = "RQST" + "\t" + latitude + "\t" + longitude + "\t" + range;
		handlerMessage = new Message();
		handlerMessage.what = StreetPostActivity.MSG_DRAW_NOTES;
		
		Thread cThread = new Thread(new TCPClient());
		cThread.start();
	}
	
	public void getPostsById(Set<String> ids) {
		msgSend = "RQST" + "\t" + "ID";
		for (String id : ids) {
			msgSend += "\t" + id;
		}
		handlerMessage = new Message();
		handlerMessage.what = StreetPostActivity.MSG_SHOW_NOTES;
		
		Thread cThread = new Thread(new TCPClient());
		cThread.start();
	}
	
	class TCPClient implements Runnable {

		@Override
		public void run() {
			try {

				InetAddress serverAddr = InetAddress.getByName(RemoteDatabase.SERVERIP);

				Log.d("TCP", "C: Connecting...");
				Socket socket = new Socket(serverAddr, RemoteDatabase.PORT);

				try {
					Log.d("TCP", "C: Sending: '" + msgSend + "'");
					PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);

					out.println(msgSend);
					socket.shutdownOutput();
					Log.d("TCP", "C: Sent.");

					BufferedReader networkReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));

					String line = networkReader.readLine();
					Log.d("TCP", "Coming word: " + line);

					ArrayList<StreetNote> msgReceived = new ArrayList<StreetNote>();
					int postedNoteId = -1;
					while (line != null && !line.equals("DATA\tEND")) {
						// case Data
						if (line.startsWith("DATA")) {
							String[] t = line.split("\t");
							StreetNote note = new StreetNote(Integer.parseInt(t[3]), Integer.parseInt(t[4]), t[5], null);
							note.id = Integer.parseInt(t[1]);
							note.timestamp = Long.parseLong(t[2]);
							
							String contents = t[6];
							while (true) {
								line = networkReader.readLine();
								Log.d("TCP", "Coming word: " + line);
								if (line.startsWith("DATA\t")) {
									note.contents = contents;
									break;
								} else {
									contents += "\n" + line;
								}
							}

							msgReceived.add(note);
						// case Done
						} else if (line.startsWith("DONE")) {
							String[] t = line.split("\t");
							postedNoteId = Integer.parseInt(t[1]);
							break;
						// case Error
						} else if (line.startsWith("ERRO")) {
							break;
						}
					}
					
					if (handlerMessage != null) {
						handlerMessage.obj = msgReceived;
						handlerMessage.arg1 = postedNoteId;
						
						updateHandler.sendMessage(handlerMessage);
						handlerMessage = null;
					}					

					Log.d("TCP", "C: Done.");
				} catch (Exception e) {
					Log.e("TCP", "S: Error", e);
				} finally {
					socket.close();
				}
			} catch (Exception e) {
				Log.e("TCP", "C: Error", e);
			}
		}
	}

}